package pso.gui;

import java.util.ArrayList;
import java.util.List;

import pso.PSOAlgorithm;
import pso.PSOAlgorithmFactory;
import pso.data.SlavePSO;
import pso.gui.slaves.SlavesTableModel;
import pso.mcpso.MCPSOAlgorithm;
import pso.mcpso.PSOEpochRunner;
import pso.velocity.MCPSOVelocityUpdateStrategy;
import evolution.data.Problem;
import evolution.problem.AckleyMinimization;
import evolution.problem.BeckerLagoMinimization;
import evolution.problem.Camelback2DMinimization;
import evolution.problem.GriewankMinimization;
import evolution.problem.MichalewiczMinimization;
import evolution.problem.OptimizationProblem;
import evolution.problem.RastriginMinimization;
import evolution.problem.Schaffer2DMinimization;
import evolution.problem.SchwefelMinimization;

public class MCSPSOBuilder {

	public MCPSOAlgorithm build(MCPSOFrame frame) {
		Problem problem = (Problem) (frame.getProblemComboBox()
				.getSelectedItem());
		OptimizationProblem optimizationProblem = null;

		switch (problem) {
		case RASTRIGIN:
			optimizationProblem = new RastriginMinimization();
			break;
		case GRIEWANK:
			optimizationProblem = new GriewankMinimization();
			break;
		case SCHWEFEL:
			optimizationProblem = new SchwefelMinimization();
			break;
		case ACKLEY:
			optimizationProblem = new AckleyMinimization();
			break;
		case MICHALEWICZ:
			optimizationProblem = new MichalewiczMinimization();
			break;
		case CAMELBACK:
			optimizationProblem = new Camelback2DMinimization();
			break;
		case BECKER_LAGO:
			optimizationProblem = new BeckerLagoMinimization();
			break;
		case SCHAFFER2:
			optimizationProblem = new Schaffer2DMinimization();
			break;
		}
		optimizationProblem.getConstraints().setDimensions(
				(Integer) (frame.getProblemDimensionsSpinner().getValue()));

		SlavesTableModel tableModel = (SlavesTableModel) frame.getSlavesTable()
				.getModel();
		int size = tableModel.getRowCount();
		List<PSOEpochRunner> slaves = new ArrayList<>(size);
		int epochLength = (Integer) (frame.getEpochLengthSpinner().getValue());

		int iterations = (Integer) (frame.getIterationsSpinner().getValue());

		for (int i = 0; i < size; i++) {
			SlavePSO slavePSO = tableModel.getElementAt(i);
			PSOAlgorithm psoAlgorithm = slavePSO.build(optimizationProblem,
					iterations);
			slaves.add(new PSOEpochRunner(psoAlgorithm, epochLength));
		}

		int swarmSize = (Integer) (frame.getSwarmSizeSpinner().getValue());
		double c1 = (Double) (frame.getC1FactorSpinner().getValue());
		double c2 = (Double) (frame.getC2FactorSpinner().getValue());
		double c3 = (Double) (frame.getC3FactorSpinner().getValue());
		double inertia = (Double) (frame.getInertiaSpinner().getValue());

		PSOAlgorithm master = PSOAlgorithmFactory
				.createConstantInertiaWeightPSO(optimizationProblem,
						iterations, swarmSize, c1, c2, inertia);
		MCPSOAlgorithm mcpsoAlgorithm = new MCPSOAlgorithm(master, epochLength);
		MCPSOVelocityUpdateStrategy strategy = new MCPSOVelocityUpdateStrategy(
				inertia, mcpsoAlgorithm);
		strategy.configureMaximumVelocity(optimizationProblem.getConstraints());
		mcpsoAlgorithm.setVelocityUpdateStrategy(strategy);
		mcpsoAlgorithm.setSlaves(slaves);
		strategy.setSlaveFactor(c3);

		return mcpsoAlgorithm;
	}
}
